package Gr

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"db2s/go-log/log"
	"db2s/parDef"
	"db2s/ref"
	"math"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

// 归并排序
func mergeSort(s, split, stype string) (mergeS []any) {
	var (
		arr = make([]any, func() (sl int) {
			if n := strings.Count(s, split); n > 0 {
				sl = n + 1
			} else {
				if len(s) > 0 {
					sl = 1
				}
			}
			return
		}())
		resolve func(arr []any, l, r int, stype string)
		//合并子表
		sf = func(a, b any) (s int) {
			switch stype {
			case "string":
				if a.(string) < b.(string) {
					return -1
				} else if a.(string) == b.(string) {
					return 0
				} else {
					return 1
				}
			case "int":
				if a.(int) < b.(int) {
					return -1
				} else if a.(int) == b.(int) {
					return 0
				} else {
					return 1
				}
			}
			return
		}
		merge = func(arr []any, l, mid, r int) {
			var tmpArr = make([]any, r-l+1)
			for i := l; i <= r; i++ {
				tmpArr[i-l] = arr[i]
			}
			var p, q = 0, mid - l + 1 //标记左右起点
			for i := l; i <= r; i++ {
				if l+p > mid { //左下标越过中点
					arr[i] = tmpArr[q]
					q++
				} else if l+q > r { //右下标越过中点
					arr[i] = tmpArr[p]
					p++
				} else if sf(tmpArr[p], tmpArr[q]) == -1 {
					arr[i] = tmpArr[p] //左小右大 取左
					p++
				} else {
					arr[i] = tmpArr[q] //右小左大 取右
					q++
				}
			}
		}
	)
	s1 := s
	var seq int
	for {
		var n int
		if n = strings.Index(s1, split); n != -1 {
			switch stype {
			case "string":
				arr[seq] = s1[:n]
			case "int":
				if sf1, err1 := strconv.Atoi(s1[:n]); err1 != nil {
					fmt.Println(err1)
					os.Exit(1)
				} else {
					arr[seq] = sf1
				}
			}
		} else {
			if len(s1) > 0 {
				switch stype {
				case "string":
					arr[seq] = s1
				case "int":
					sf1, _ := strconv.Atoi(s1)
					arr[seq] = sf1
				}
			}
			break
		}
		seq++
		s1 = s1[n+len(split):]
	}
	//划分子表
	resolve = func(arr []any, l, r int, stype string) {
		if l < r {
			var mid = l + ((r - l) >> 1)
			resolve(arr, l, mid, stype)
			resolve(arr, mid+1, r, stype)
			merge(arr, l, mid, r)
		}
	}
	resolve(arr, 0, len(arr)-1, stype)
	return arr
}

//func mergeSourt(buffC chan any, dtype string, Limitseq int64) (EndRows map[string]any) {
//	var (
//		buff bytes.Buffer
//	)
//	EndRows = make(map[string]any)
//	for k := range buffC {
//		if k != nil && strings.EqualFold(fmt.Sprintf("%v", reflect.TypeOf(k)), "[]*string") {
//			for _, v := range k.([]*string) {
//				buff.WriteString(*v)
//				buff.WriteString(string(RowsDataSplict))
//			}
//		}
//	}
//	sf := buff.String()
//	buff.Reset()
//	if strings.HasSuffix(sf, string(RowsDataSplict)) {
//		sf = sf[:len(sf)-len(string(RowsDataSplict))]
//	}
//	arr := mergeSort(sf, string(RowsDataSplict), dtype)
//	switch dtype {
//	case "string":
//		if len(arr) > 0 {
//			if int64(len(arr)) > Limitseq {
//				EndRows["columnName"] = arr[Limitseq]
//			} else {
//				EndRows["columnName"] = arr[len(arr)-1]
//			}
//		}
//	case "int":
//		if len(arr) > 0 {
//			if int64(len(arr)) > Limitseq {
//				EndRows["columnName"] = arr[Limitseq]
//			} else {
//				EndRows["columnName"] = arr[len(arr)-1]
//			}
//		}
//	}
//	return
//}

func resultTypeCheck(e, s string, r any) (err error) {
	switch s {
	case "map":
		if !strings.EqualFold(fmt.Sprintf("%v", reflect.TypeOf(r)), "map[string]interface {}") {
			err = errors.New(fmt.Sprintf("%v result type not is map[string]interface{}, it is %v", e, reflect.TypeOf(r)))
		}
	case "sMap":
		if !strings.EqualFold(fmt.Sprintf("%v", reflect.TypeOf(r)), "[]map[string]interface {}") {
			err = errors.New(fmt.Sprintf("%v result type not is []map[string]interface{}, it is %v", e, reflect.TypeOf(r)))
		}
	default:
		err = errors.New(fmt.Sprintf("input type "))
	}
	return
}
func isNumeric(s string) bool {
	// 正则表达式：^ 表示开始，$ 表示结束，\d 表示数字，\. 表示小数点
	re := regexp.MustCompile(`^[\d.]+$`)
	return re.MatchString(s)
}

func rowsLimitC(limit int) (p string) {
	if limit > 0 {
		p = fmt.Sprintf(" limit %v", limit)
	}
	return
}
func tableObject(schema, table, partition string) (p string) {
	p = fmt.Sprintf(" `%v`.`%v` ", schema, table)
	if len(partition) > 0 && !strings.EqualFold(partition, "single") {
		p = fmt.Sprintf(" `%v`.`%v` PARTITION(%v)", schema, table, partition)
	}
	return
}
func whereFilter(where string) (p string) {
	if len(where) > 0 {
		p = fmt.Sprintf(" and %v", where)
	}
	return
}
func hitSpecify(s global.StartPart) (hitIndexName string) {
	//指定partition name会导致无法使用索引，进行全表扫描，且该sql为查询数据，已经通过索引列范围确定查询范围，所以不需要指定分区
	if len(s.SelectColumn.IndexName) > 0 {
		hitIndexName = fmt.Sprintf(" /*+ index(T %v) */ ", s.SelectColumn.IndexName)
	}
	return
}
func CalculateDecimalSize(M int64) int {
	if M < 0 {
		return 0 // M 不能为负
	}
	// 使用公式: FLOOR((M + 1) / 2) + 1
	return int(math.Floor(float64(M+1)/2)) + 1
}
func columnInvisibleOptions(invisible bool) (ch string) {
	if invisible {
		return " /*!80023 INVISIBLE */"
	}
	return
}
func columnAutoIncrementOptions(autoIncrement bool) (ch string) {
	if autoIncrement {
		return "auto_increment"
	}
	return
}
func specifyScn(s string) (p string) {
	if !strings.EqualFold(s, "0") && len(s) > 0 {
		p = fmt.Sprintf("AS OF SCN %v", s)
	}
	return
}
func colAndWhere(s global.StartPart) (res colAndWhereResult, err error) {
	var (
		tableSql = TableSql{}
		event    = "[mysqlColAndWhere]"
	)
	if res.selectColumn, res.asSelectColumn, err = tableSql.SelectColumn(s.SelectColumn); err != nil || len(res.selectColumn) == 0 {
		err = errors.New(fmt.Sprintf("%v get sql select Column fail. Execution process:{chema:%v,table:%v,select column:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.SelectColumn, err))
		return
	}
	if res.whereCondition, err = tableSql.WhereGenerate(s.WhereGenerate); err != nil {
		err = errors.New(fmt.Sprintf("%v get sql select where Condition fail. Execution process:{chema:%v,table:%v,select where Condition:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.WhereGenerate, err))
		return
	}
	if res.orderByColumn, err = tableSql.OrderBY(s.WhereGenerate); err != nil {
		return
	}
	return
}

func removeQuotes(s string) string {
	// 定义正则表达式，匹配字符串开头和结尾的引号或反引号
	re := regexp.MustCompile(`^(["` + "`" + `]|["` + "`" + `])|(["` + "`" + `]|["` + "`" + `])$`)
	// 使用正则替换引号和反引号为空字符串
	return re.ReplaceAllString(s, "")
}
func columnNameRemoveQuotes(s []string) (res []string) {
	for _, v := range s {
		res = append(res, removeQuotes(v))
	}
	return
}
func getMiddleBracket(s string) (p string) {
	switch {
	case strings.HasPrefix(s, "(") && strings.HasSuffix(s, ")"):
		p = s[1 : len(s)-1]
	case !strings.HasPrefix(s, "(") && strings.Contains(s, "(") && strings.HasSuffix(s, ")"):
		bef := strings.Index(s, "(")
		aft := strings.Index(s, ")")
		if bef != -1 && aft != -1 {
			p = s[bef+1 : aft]
		} else {
			p = s
		}
	default:
		p = s
	}
	return
}
func funcParameterSplit(s string) (r []string) {
	var splitSymbol = ","
	lastCommaIndex := strings.LastIndex(s, splitSymbol)
	// 如果找到逗号，则进行切割
	if lastCommaIndex != -1 {
		r = append(r, strings.Split(s[:lastCommaIndex], splitSymbol)...) // 前部分
		r = append(r, s[lastCommaIndex+1:])                              // 后部分
	} else {
		r = append(r, s) // 如果没有逗号，则只添加原字符串
	}
	return
}
func nullEmpty(r string) (s string) {
	switch r {
	case "<null>":
	default:
		s = r
	}
	return
}
func subPartSumMax(s []global.TablePartitionConfig) int {
	var sumMax int
	for _, v := range s {
		p := len(v.SubPartMeta)
		if p > sumMax {
			sumMax = p
		}
	}
	return sumMax
}
func legitimateIf(event, sqlStr string, s any, active ETL.InstanceActiveS) error {
	var (
		schema, table string
		db            map[string]*sql.DB
	)
	switch fmt.Sprintf("%v", reflect.TypeOf(s)) {
	case "global.TableSumInput":
		r := s.(global.TableSumInput)
		schema = r.TableInfo.Schema
		table = r.TableInfo.BackendTableName
		db = r.Db
	case "global.StartPart":
		r := s.(global.StartPart)
		schema = r.TableInfo.Schema
		table = r.TableInfo.BackendTableName
		db = r.DB
	}
	if active.DB == nil || len(schema) == 0 || len(table) == 0 || len(db) == 0 {
		return errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{schema:%v,table:%v,sql:%v,shard:%v,db:%v}", event, schema, table, sqlStr, "single", db))
	}
	return nil
}
func stringNullActive(t any) (r any) {
	switch fmt.Sprintf("%v", t) {
	case "<null>", "<entry>":
		r = "NULL"
	default:
		r = fmt.Sprintf("%v", t)
	}
	return
}
func mapNullActive(s map[string]any) (p map[string]any) {
	p = make(map[string]any)
	for q, t := range s {
		switch fmt.Sprintf("%v", t) {
		case "<null>", "<entry>":
			p[q] = "NULL"
		default:
			p[q] = fmt.Sprintf("%v", t)
		}
	}
	return
}
func mapStringToStruct(s map[string]any, p any) (err error) {
	var jsonData []byte
	jsonData, err = json.Marshal(s)
	if err != nil {
		return
	}
	// 反序列化JSON字符串到结构体
	err = json.Unmarshal(jsonData, p)
	if err != nil {
		return
	}
	return
}
func mapAnyToString(s map[string]any) (p map[string]string) {
	r := mapNullActive(s)
	p = make(map[string]string)
	for q, t := range r {
		switch fmt.Sprintf("%v", t) {
		case "<null>", "<entry>":
			p[q] = "NULL"
		default:
			p[q] = fmt.Sprintf("%v", t)
		}
	}
	return
}

type execSqlS struct {
	DB        map[string]*sql.DB
	ShardName string
	Input     global.StartPartConfigInputP
}

func getExecSqlData(s any) (x execSqlS) {
	switch s.(type) {
	case global.TablesMetaInfoInput:
		p := s.(global.TablesMetaInfoInput)
		x = execSqlS{
			DB:    p.DB,
			Input: p.Input,
		}
	case global.SchemaObjectInput:
		p := s.(global.SchemaObjectInput)
		x = execSqlS{
			DB:    p.DB,
			Input: p.Input,
		}
	case global.GetColumnTypeInput:
		p := s.(global.GetColumnTypeInput)
		x = execSqlS{
			DB:    p.DB,
			Input: p.Input,
		}
	case global.TableSumInput:
		p := s.(global.TableSumInput)
		x = execSqlS{
			DB:    p.Db,
			Input: p.Input,
		}
	case global.RowsDataInput:
		p := s.(global.RowsDataInput)
		x = execSqlS{
			DB:    p.DB,
			Input: p.Input,
		}
	case global.DBGetCharacterS:
		p := s.(global.DBGetCharacterS)
		x = execSqlS{DB: p.DB, Input: p.Input}
	case global.StartPart:
		p := s.(global.StartPart)
		x = execSqlS{DB: p.DB, Input: p.Input}
	case global.DbParameterOptimizerS:
		p := s.(global.DbParameterOptimizerS)
		x = execSqlS{
			DB:        p.DB,
			Input:     p.Input,
			ShardName: p.ShardName,
		}
	case conDbQuery:
		p := s.(conDbQuery)
		x = execSqlS{
			DB:        p.DB,
			ShardName: p.ShardName,
			Input:     p.Input,
		}
	}
	return
}

type ExecSqlInputS struct {
	Ss           any
	Event        string
	SelectSqlStr string
	UpdateSqlStr []string
	Expect       string
	ShardName    string
}

func ExecSelectSql(e ExecSqlInputS) (timeout int64, res any, err error) {
	var (
		x               = getExecSqlData(e.Ss)
		expectTypeValue string
	)
	if len(e.ShardName) == 0 {
		e.ShardName = "single"
	}
	active := ETL.InstanceActiveS{DBType: DBType, DB: x.DB[e.ShardName], StopTime: x.Input.SqlExecStopTime, SqlMode: x.Input.SqlMode}
	if len(x.DB) == 0 || active.DB == nil {
		err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", e.SelectSqlStr, e.ShardName, x.DB, err))
		return
	}
	if timeout, res, err = active.SqlQuery(e.SelectSqlStr, e.Expect); err != nil || res == nil {
		if err != nil {
			err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,err:%v}", e.SelectSqlStr, err))
		}
		return
	}
	switch e.Expect {
	case ETL.Map:
		expectTypeValue = "map[string]interface {}"
	case ETL.StringGarth:
		expectTypeValue = "[]string"
	case ETL.String:
		expectTypeValue = "string"
	case ETL.StringPoint:
		expectTypeValue = "*string"
	case ETL.StringPointGarth:
		expectTypeValue = "[]*string"
	case ETL.GarthStringPointGarth:
		expectTypeValue = "[][]*string"
	case ETL.SMap:
		expectTypeValue = "[]map[string]interface {}"
	case ETL.FlowAny:
		expectTypeValue = "chan interface {}"
	case ETL.FlowString:
		expectTypeValue = "chan string"
	}
	if !strings.EqualFold(fmt.Sprintf("%v", reflect.TypeOf(res)), expectTypeValue) {
		err = errors.New(fmt.Sprintf("sql exec fail. result type mismatch! return:%v want:[]string.process:{sql:%v,result:%v}", reflect.TypeOf(res), e.SelectSqlStr, res))
		return
	}
	return
}
func newGetExecSqlData(s any) (x newExecSqlS, err error) {
	switch s.(type) {
	case Parameter:
		p := s.(Parameter)
		x = newExecSqlS{
			DB:      p.Con,
			options: p.Options,
		}
	case parDef.Parameter:
		p := s.(parDef.Parameter)
		x = newExecSqlS{
			DB: p.Con,
			options: Options{
				Scn:      p.Options.Scn,
				StopTime: p.Options.StopTime,
				WhereSql: p.Options.WhereSql,
				//WhereAdd: p.Options.WhereAdd,
			},
		}
	default:
		err = ref.ErrAddPrintf("newGetExecSqlData", errors.New(fmt.Sprintf("type not match. curry type is %v", reflect.TypeOf(s))))
	}
	return
}
func newExecSelectSql(e ExecSqlInputS) (timeout int64, res any, err error) {
	var (
		x               newExecSqlS
		event           = "[newExecSelectSql]"
		expectTypeValue string
	)
	if x, err = newGetExecSqlData(e.Ss); err != nil {
		err = ref.ErrAddPrintf(event, err)
		return
	}
	if len(e.ShardName) == 0 {
		e.ShardName = "single"
	}
	active := ETL.InstanceActiveS{DBType: DBType, DB: x.DB, FixRows: x.options.FixRows, StopTime: x.options.StopTime, SqlMode: x.options.SqlMode}
	if active.DB == nil {
		err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", e.SelectSqlStr, e.ShardName, x.DB, err))
		return
	}
	if timeout, res, err = active.SqlQuery(e.SelectSqlStr, e.Expect); err != nil || res == nil {
		if err != nil {
			err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,err:%v}", e.SelectSqlStr, err))
		}
		return
	}
	switch e.Expect {
	case ETL.Map:
		expectTypeValue = "map[string]interface {}"
	case ETL.StringGarth:
		expectTypeValue = "[]string"
	case ETL.String:
		expectTypeValue = "string"
	case ETL.StringPoint:
		expectTypeValue = "*string"
	case ETL.StringPointGarth:
		expectTypeValue = "[]*string"
	case ETL.GarthStringPointGarth:
		expectTypeValue = "[][]*string"
	case ETL.SMap:
		expectTypeValue = "[]map[string]interface {}"
	case ETL.FlowAny:
		expectTypeValue = "chan interface {}"
	case ETL.FlowString:
		expectTypeValue = "chan string"
	}
	if !strings.EqualFold(fmt.Sprintf("%v", reflect.TypeOf(res)), expectTypeValue) {
		err = errors.New(fmt.Sprintf("sql exec fail. result type mismatch! return:%v want:[]string.process:{sql:%v,result:%v}", reflect.TypeOf(res), e.SelectSqlStr, res))
		return
	}
	return
}
func ExecUpdateSql(e ExecSqlInputS) (timeout int64, err error) {
	var (
		x = getExecSqlData(e.Ss)
	)
	if len(e.ShardName) == 0 {
		e.ShardName = "single"
	}
	active := ETL.InstanceActiveS{DBType: DBType, DB: x.DB[e.ShardName], FixRows: x.Input.FixRows, StopTime: x.Input.SqlExecStopTime, SqlMode: x.Input.SqlMode}
	if len(x.DB) == 0 || active.DB == nil {
		err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", e.SelectSqlStr, e.ShardName, x.DB, err))
		return
	}
	if _, err = active.Update(e.UpdateSqlStr); err != nil {
		err = errors.New(fmt.Sprintf("sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", e.SelectSqlStr, e.ShardName, x.DB, err))
		return
	}
	return
}
func newExecUpdateSql(event, schemaTable string, active any, UpdateSqlStr []string) (execTime int64, err error) {
	defer func() {
		err = ref.RecoverPanic(event, recover())
	}()
	log.MainLog().DebugS(event, schemaTable, fmt.Sprintf(" exec sql is %v.", UpdateSqlStr))
	//if active.DB == nil {
	//	err = fmt.Errorf("sql exec fail. connection point is nil")
	//	log.ErrorLog().ErrorS(event, schemaTable, fmt.Sprintf("sql exec fail. sql is %v connection point is nil", UpdateSqlStr))
	//	return
	//}
	if execTime, err = ETL.Update(active, []string{}, UpdateSqlStr); err != nil {
		log.ErrorLog().ErrorS(event, schemaTable, fmt.Sprintf("sql exec fail. exec sql is %v error is %v", UpdateSqlStr, err))
		return
	}
	log.MainLog().DebugS(event, schemaTable, fmt.Sprintf(" sql is %v, bath timeOut is %v ms.", UpdateSqlStr, execTime))
	return
}
func QueryColValManage(val any) (newVal any) {
	if val == nil || len(fmt.Sprintf("%v", val)) == 0 || strings.EqualFold(fmt.Sprintf("'%v'", val), "'<nil>'") {
		switch {
		case len(fmt.Sprintf("%v", val)) == 0:
			newVal = "<entry>" //空字符串
		case fmt.Sprintf("%v", val) == "<nil>":
			newVal = "<null>" //null
		}
		return
	} else {
		newVal = val
	}
	switch val.(type) {
	case string:
		if val == nil {
			return
		}
		switch {
		case strings.Contains(val.(string), "SRID:") && strings.Contains(val.(string), "AXIS:OGC"): //wkt模式
			//var err error
			//if newVal, err = GeomWktToJson(val); err != nil {
			//	return err
			//}
		default:
			return newVal
		}
	default:
		return newVal
	}
	return
}
func forExecQuerySql(event string, parameter any, Expect string, execSql []string) (result global.Return, err error) {
	defer func() {
		if err != nil {
			err = ref.ErrAddPrintf("forExecQuerySql", err)
		}
	}()
	for _, v := range execSql {
		result.Sql = v
		if result.TimeOut, result.Result, err = newExecSelectSql(ExecSqlInputS{
			Ss:           parameter,
			Event:        event,
			SelectSqlStr: result.Sql,
			Expect:       Expect,
		}); err != nil || result.Result == nil {
			continue
		} else {
			return
		}
	}
	return
}

func stringAnyToInt64(s any) (res int64, err error) {
	switch pp := stringNullActive(s); pp.(type) {
	case string:
		if !strings.EqualFold(pp.(string), "NULL") {
			return strconv.ParseInt(fmt.Sprintf("%v", pp), 10, 64)
		}
	}
	return
}

func stringAnyToFloat64(s any) (res float64, err error) {
	switch pp := stringNullActive(s); pp.(type) {
	case string:
		if !strings.EqualFold(pp.(string), "NULL") {
			return strconv.ParseFloat(fmt.Sprintf("%v", pp), 64)
		}
	}
	return
}
func generalComment(prefix, s string) string {
	var replicationStr = []string{"'", ";"}
	switch {
	case s == "<entry>", s == "<null>", s == "''", s == "NULL":
		return fmt.Sprintf("%v ''", prefix)
	case len(s) == 0:
		return ""
	case func() bool {
		var e bool
		for _, v := range replicationStr {
			if strings.Contains(s, v) {
				e = true
			}
		}
		return e
	}():
		var q = s
		for _, v := range replicationStr {
			if strings.Contains(s, v) {
				q = strings.ReplaceAll(q, fmt.Sprintf("%v", v), fmt.Sprintf("\\%v", v))
			}
		}
		return fmt.Sprintf("%v '%v'", prefix, q)
	default:
		return fmt.Sprintf("%v '%v'", prefix, s)
	}
}
func metaBaseInit(meta any) (result MetaBaseInitResult, err error) {
	result = MetaBaseInitResult{}
	if result.columnMeta, err = columnMetaBaseInit(meta.(map[string]any)["columnMe"]); err != nil {
		return
	}
	switch meta.(map[string]any)["columnMetaMap"].(type) {
	case []parDef.ColMetaMapS:
		result.columnMetaMap = meta.(map[string]any)["columnMetaMap"].([]parDef.ColMetaMapS)
	}
	switch meta.(map[string]any)["indexMe"].(type) {
	case []parDef.IndexColumnMe:
		result.indexMeta = meta.(map[string]any)["indexMe"].([]parDef.IndexColumnMe)
	}
	switch meta.(map[string]any)["partMe"].(type) {
	case parDef.PartMetaData:
		result.partMe = meta.(map[string]any)["partMe"].(parDef.PartMetaData)
	}
	switch meta.(map[string]any)["commentMe"].(type) {
	case string:
		result.Comment = meta.(map[string]any)["commentMe"].(string)
	}
	return
}

func modifyGetDbQueryOptions(s ETL.InstanceActiveS, Expect string) ETL.InstanceActiveS {
	s.SqlMode = true
	s.DBType = DBType
	s.Expect = Expect
	s.GisValFunc = QueryColValManage
	return s
}
func getTableName(schema, table any) (tableName string) {
	return fmt.Sprintf(" %v.%v ", schema, table)
}
func getLikeTable(table string) (res string) {
	switch {
	case table == "*":
		return ""
	case strings.Contains(table, "%"):
		return fmt.Sprintf("and TABLE_NAME like '%v'", table)
	default:
		return fmt.Sprintf("and TABLE_NAME = '%v'", table)
	}
}
func getLikeSeqName(table string) (res string) {
	switch {
	case table == "*":
		return ""
	case strings.Contains(table, "%"):
		return fmt.Sprintf("and NAME like '%v'", table)
	default:
		return fmt.Sprintf("and NAME = '%v'", table)
	}
}
func getSysObjectView(p ...string) (sysView []string) {
	return p
}
func generalQuerySysObjectSql(s, t string, o []string, body func(o, s, t string) string) (res []string) {
	for _, v := range o {
		res = append(res, body(v, s, t))
	}
	return
}

func sqlExec(event string, schemaTable string, dbOptions any, execSqlFunc func(S any, sqlStr []string, expect string) (global.Return, error), execSql []string, expect string) (result global.Return, err error) {
	log.MainLog().DebugS(event, schemaTable, fmt.Sprintf(" sql is %v.", execSql))
	if execSqlFunc == nil {
		log.MainLog().WarnS(event, schemaTable, fmt.Sprintf(" ExecSqlFunc is nil."))
		return
	}
	if result, err = execSqlFunc(dbOptions, execSql, expect); err != nil {
		err = ref.ErrAddPrintf(event, err)
		log.ErrorLog().ErrorS(event, schemaTable, fmt.Sprintf(" sql is %v, error is %v.", result.Sql, err))
		return
	}
	log.MainLog().DebugS(event, schemaTable, fmt.Sprintf(" sql is %v, bath timeOut is %v ms,query result is %v.", result.Sql, result.TimeOut, result.Result))
	return
}
func resultExec(event string, schemaTable string, execFunc func(s any, execFunc any) (any, error), res global.Return, funcParameter any, funcDef any) (result global.Return, err error) {
	result = res
	if execFunc == nil {
		log.MainLog().WarnS(event, schemaTable, fmt.Sprintf(" ExecFunc is nil."))
		return
	}
	if result.Result, err = execFunc(funcParameter, funcDef); err != nil {
		err = ref.ErrAddPrintf(event, err)
		log.ErrorLog().ErrorS(event, schemaTable, fmt.Sprintf(" sql is %v, error is %v.", result.Sql, err))
		return
	}
	log.MainLog().DebugS(event, schemaTable, fmt.Sprintf(" sql is %v, bath timeOut is %v ms,query result is %v.", result.Sql, result.TimeOut, result.Result))
	return
}

func getExecFuncParameterValueBase(ctx context.Context) (schema, table string) {
	schema = parDef.GetParameterValueAnyToString(parDef.GetFuncParameterValue(ctx, parDef.GetSchemaParameterValue()))
	table = parDef.GetParameterValueAnyToString(parDef.GetFuncParameterValue(ctx, parDef.GetTableParameterValue()))
	return
}
func getExecSqlFuncOptionsValueBase(ctx context.Context) (res ETL.ReadOpt) {
	return parDef.GetReadDbExecOptions(parDef.GetFuncParameterValue(ctx, parDef.GetDbReadOptionsParameterValue()))
}
func getSqlExecFuncParameterValue(ctx context.Context, event string, objectView []string, body func(o string, s string, t string) string) (eventNew string, schemaTable string, dbOptions any, execSqlFunc func(S any, sqlStr []string, expect string) (global.Return, error), execSql []string, expect string) {
	var schema, table = getExecFuncParameterValueBase(ctx)
	execSql = generalQuerySysObjectSql(schema, table, getSysObjectView(objectView...), body)
	dbOptions = getExecSqlFuncOptionsValueBase(ctx)
	expect = parDef.GetParameterValueAnyToString(parDef.GetFuncParameterValue(ctx, parDef.GetExpectParameterValue()))
	//execSqlFunc = parDef.GetDbExecSqlFunc(parDef.GetFuncParameterValue(ctx, parDef.GetExecSqlFuncParameterValue()))
	return event, getTableName(schema, table), dbOptions, execSqlFunc, execSql, expect
}
func getExternalExecFuncParameterValue(ctx context.Context, event string, res global.Return, funcParameter any, funcDef any) (eventNew string, schemaTable string, externalExecFunc func(s any, execFunc any) (any, error), result global.Return, funcParameterNew any, funcDefNew any) {
	externalExecFunc = parDef.GetExternalExecFunc(parDef.GetFuncParameterValue(ctx, parDef.GetExternalExecFuncParameterValue()))
	return event, getTableName(getExecFuncParameterValueBase(ctx)), externalExecFunc, res, funcParameter, funcDef
}
func getJsonNameValue(getJsonValue func(s any, key string) (any, error), meta any, name string) (result string) {
	var rr any
	var err error
	if getJsonValue != nil {
		if rr, err = getJsonValue(meta, name); err != nil {
			return
		}
	}
	return fmt.Sprintf("%v", rr)
}
